#ifndef DW_SYSTEM_SIGNAL_HPP
# define DW_SYSTEM_SIGNAL_HPP

#	ifdef DW_TRACE_INCLUDES
#		pragma message("-- include dw/system/signal.hpp")
#	endif // DW_TRACE_INCLUDES

namespace dw
{
	namespace system
	{
		
		template <typename Arg1Type = void, typename Arg2Type = void, typename Arg3Type = void, typename Arg4Type = void>
		class Signal
		{
		public:

			Signal() {}

			~Signal() {}



			void operator+=(_Slot<Arg1Type, Arg2Type, Arg3Type, Arg4Type>* slot) { connect(slot); }


			
			void	connect(_Slot<Arg1Type, Arg2Type, Arg3Type, Arg4Type>* slot) { _slots.push_back(slot); }

			void	emit(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3, Arg4Type arg4) const 
			{
				for (unsigned i = 0; i < _slots.size(); ++i)
					_slots[i]->call(arg1, arg2, arg3, arg4);
			}
			
		private:

			std::vector<_Slot<Arg1Type, Arg2Type, Arg3Type, Arg4Type>* > _slots;

		};
		
		template <typename Arg1Type, typename Arg2Type, typename Arg3Type>
		class Signal<Arg1Type, Arg2Type, Arg3Type>
		{
		public:

			Signal() {}

			~Signal() {}



			void operator+=(_Slot<Arg1Type, Arg2Type, Arg3Type>* slot) { connect(slot); }


			
			void	connect(_Slot<Arg1Type, Arg2Type, Arg3Type>* slot) { _slots.push_back(slot); }


			void	emit(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3) const 
			{
				for (unsigned i = 0; i < _slots.size(); ++i)
					_slots[i]->call(arg1, arg2, arg3);
			}
			
		private:

			std::vector<_Slot<Arg1Type, Arg2Type, Arg3Type>* > _slots;

		};
		
		template <typename Arg1Type, typename Arg2Type>
		class Signal<Arg1Type, Arg2Type>
		{
		public:

			Signal() {}

			~Signal() {}



			void operator+=(_Slot<Arg1Type, Arg2Type>* slot) { connect(slot); }


			
			void	connect(_Slot<Arg1Type, Arg2Type>* slot) { _slots.push_back(slot); }
			
			void	emit(Arg1Type arg1, Arg2Type arg2) const 
			{
				for (unsigned i = 0; i < _slots.size(); ++i)
					_slots[i]->call(arg1, arg2);
			}
			
		private:

			std::vector<_Slot<Arg1Type, Arg2Type>* > _slots;

		};
		
		template <typename Arg1Type>
		class Signal<Arg1Type>
		{
		public:

			Signal() {}

			~Signal() {}



			void operator+=(_Slot<Arg1Type>* slot) { connect(slot); }


		
			void	connect(_Slot<Arg1Type>* slot) { _slots.push_back(slot); }
			
			void	emit(Arg1Type arg1) const 
			{
				for (unsigned i = 0; i < _slots.size(); ++i)
					_slots[i]->call(arg1);
			}
			
		private:
			
			std::vector<_Slot<Arg1Type>* > _slots;

		};

		template <>
		class Signal<>
		{
		public:

			Signal() {}
		
			~Signal() {}



			void operator+=(_Slot<>* slot) { connect(slot); }



			void	connect(_Slot<>* slot) { _slots.push_back(slot); }
			
			void	emit() const 
			{
				for (unsigned i = 0; i < _slots.size(); ++i)
					_slots[i]->call();
			}
			
		private:
			
			std::vector<_Slot<>* > _slots;

		};

	} // namespace system
} // namespace dw

#endif // DW_SYSTEM_SIGNAL_HPP
